/**
 * 
 */
package com.geezdata.cps.base.redis;

import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.shiro.cache.CacheException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

import com.alibaba.fastjson.JSON;
import com.geezdata.cps.base.constant.ShiroConstants;

import redis.clients.jedis.exceptions.JedisConnectionException;

/**
 * @author sszheng
 * @date 创建时间：2017年11月6日 上午10:18:14
 *
 */
public class RedisManager {
	private static final Logger logger = LoggerFactory.getLogger(RedisManager.class);

	@Autowired
	private RedisTemplate<Object, Object> redisTemplate;
	@Autowired
	private JedisConnectionFactory jedisConnectionFactory;
	
	@SuppressWarnings("unchecked")
	public <T> T get(String projectName, String domainName, String key, Class<T> clazz) throws CacheException {
		String redisKey = getCacheKey(projectName, domainName, key);
		logger.debug("RedisCache::get {}", redisKey); 
		
		if (redisKey == null || !redisTemplate.hasKey(redisKey)) {
			return null;
		}
		
		redisTemplate.boundValueOps(redisKey).expire(ShiroConstants.EXPIRE_TIME, TimeUnit.SECONDS);
		Object value = redisTemplate.boundValueOps(redisKey).get();

		return (T)value;
	}

	public <T> T put(String projectName, String domainName, String key, T value, Class<T> clazz) throws CacheException {
		String redisKey = getCacheKey(projectName, domainName, key);
		logger.debug("RedisCache::put {}", redisKey);
		logger.debug("RedisCache::put value {}", JSON.toJSONString(value));
		T old = get(projectName, domainName, key, clazz);
		
		redisTemplate.boundValueOps(redisKey).set(value);
		redisTemplate.boundValueOps(redisKey).expire(ShiroConstants.EXPIRE_TIME, TimeUnit.SECONDS);
        return old;
	}

	public <T> T remove(String projectName, String domainName, String key, Class<T> clazz) throws CacheException {
		String redisKey = getCacheKey(projectName, domainName, key);
		logger.debug("RedisCache::remove {}", redisKey);
		T old = get(projectName, domainName, key, clazz);
		redisTemplate.delete(redisKey);
		return old;
	}
	
	public void removeBatch(String projectName, String domainName) throws CacheException {
		String redisKey = getCacheKey(projectName, domainName, "*");
		logger.debug("RedisCache::remove {}", redisKey);
		Set<Object> keys = redisTemplate.keys(redisKey);
		redisTemplate.delete(keys);
	}
	
	public void removeBatch(String key) throws CacheException {
		String redisKey = "*" + key + "*";
		Set<Object> keys = redisTemplate.keys(redisKey);
		redisTemplate.delete(keys);
	}
	
	public void removeBatchMybatis(String key) {
		JedisConnection connection = null;
        try {
            connection = (JedisConnection) jedisConnectionFactory.getConnection();
            Set<byte[]> keySet = connection.keys(("*"+ key +"*").getBytes());
            byte[][] keys = keySet.stream().toArray(byte[][]::new );
            if(keys.length == 0) {
            	return ;
            }
            connection.del(keys);
        }
        catch (JedisConnectionException e){
        	logger.error(e.getMessage(), e);
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
	}
	
	private String getCacheKey(String projectName, String domainName, String key) {
		return projectName + ":" + domainName + ":" + key;
	}
}
